package main

import (
	"fmt"
	"gofirst/ch02variable/varscope"
	"reflect"
)

func declareVariableBasic() {
	// 1.变量定义、再初始化
	var a int
	a = 10
	fmt.Println(a)

	// 2.定义变量的同时，初始化
	var b int = 20
	fmt.Println(b)

	// 3.根据值，自动进行类型推断。并且只有在初始化的时候才能这么用
	var c = 30
	fmt.Println(c)

	// 4.海象运算符，这种只能在函数内部声明局部变量。不能定义全局变量
	d := 40
	fmt.Println(d)

	var i int = 10
	var j = 10
	h := 10
	fmt.Println(i, j, h)

	// 多变量定义
	var aa, bb, cc int
	aa, bb, cc = 10, 20, 30
	fmt.Println(aa, bb, cc)

	var aaa, bbb, ccc int = 100, 200, 300
	fmt.Println(aaa, bbb, ccc)

	// 同时定义多个不同数据类型的变量
	var (
		age  int
		name string
	)
	age, name = 18, "john"
	fmt.Println(age, name)
}

func declareConstantVariable() {
	//声明常量, 常量是不能修改的
	const PI = 3.1415926

	r := 2.0
	var c float64

	c = 2 * PI * r
	fmt.Println("周长：", c)

	// 常量定义完，可以不使用
	const (
		UNKNOWN = -1
		FEMALE  = 1
		MALE    = 0
	)

	//常量组如不指定类型和初始化值，该类型和值，与上一行的类型一致
	const (
		x int = 16
		y
		s = "abc"
		z
	)

	fmt.Println("y值：", y, "y类型：", reflect.TypeOf(y))
	fmt.Println("z值：", z, "z类型：", reflect.TypeOf(z))

	// 1.常量的数据类型可以是：bool, 数值，字符串
	// 2.不曾使用的常量，在编译的时候不会报错
}

func useIotaDeclareVariable() {
	// iota是golang中的常量计数器
	// iota只能和const一起使用，和var无关

	const (
		Book  = iota //计算器
		Cloth        //行
		Phone
		DeskTop
	)
	//0,1,2,3 本身不重要， 重要的是这几个值不一样
	fmt.Println(Book, Cloth, Phone, DeskTop)

	//iota你真的懂了吗？
	//1. iota只能在常量组中是使用
	//2. 不同的const定义块互相不干扰
	const (
		Unknown = iota
		Female
		Male
	)
	fmt.Println(Unknown, Female, Male)

	//3.没有表达式的常量定义，复用上一行的表达式
	//4.从第一行开始，iota从0逐行加一
	const (
		//g = "start"
		a    = iota       //iota  = 0, 上一行的g="start"如果启用，这里恶的iota=1
		b    = 10         //iota = 1 每一行iota加一
		c                 // c=10 , iota = 2
		d, e = iota, iota //iota=3
		f    = iota       //iota=4
		//iota代表的是这里(const声明组里)的行数
	)

	fmt.Println(a, b, c, d, e, f)

}

//Go 中 main 包默认不会加载其他文件， 而其他包都是默认加载的。
//如果 main 包有多个文件，则在执行的时候需要将其它文件都带上，即执行 go run *.go。
func main() {
	//变量的定义
	declareVariableBasic()

	//匿名变量， _
	//go中变量定义了不适用的话，是不行的
	a, _ := fmt.Println('a')
	fmt.Println(a)

	//常量
	declareConstantVariable()

	//use iota 声明常量
	useIotaDeclareVariable()

	//变量作用域
	varscope.TestVarScope()

}
